package com.filex.ads.nativeads;

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.View;
import com.filex.ads.common.logging.Logger;
import com.filex.ads.network.AdResponse;
import com.filex.ads.network.TrackingRequest;
import org.json.JSONArray;
import org.json.JSONObject;

public class InternalNativeAd extends BaseNativeAd  implements ImpressionInterface, ClickInterface  {


    private static final int DEFAULT_IMPRESSION_MIN_TIME_VIEWED_MS = 1000;
    private static final int DEFAULT_IMPRESSION_MIN_PERCENTAGE_VIEWED = 50;

    @NonNull private Context mContext;

    // Basic fields
    @Nullable
    private String mMainImageUrl;
    @Nullable private String mIconImageUrl;
    @Nullable private String mClickDestinationUrl;
    @Nullable private String mCallToAction;
    @Nullable private String mTitle;
    @Nullable private Double mStarRating;
    @Nullable private String mDisplayUrl;
    @Nullable private String mSponsored;
    @Nullable private String mDesc;
    @Nullable private String mDesc2;
    @Nullable private String mLikes;
    @Nullable private String mDownloads;

    // Impression logistics
    private boolean mImpressionRecorded;
    private int mImpressionMinTimeViewed;
    private int mImpressionMinPercentageViewed;
    private Integer mImpressionMinVisiblePx;
    private ImpressionTracker mImpressionTracker;
    private NativeClickHandler mClickHandler;
    private JSONObject mAdJSONObject;

    protected InternalNativeAd(@NonNull Context context, @NonNull AdResponse adResponse) {
        mContext = context.getApplicationContext();
        mImpressionMinTimeViewed = DEFAULT_IMPRESSION_MIN_TIME_VIEWED_MS;
        mImpressionMinPercentageViewed = DEFAULT_IMPRESSION_MIN_PERCENTAGE_VIEWED;
        mImpressionMinVisiblePx = null;
        mImpressionTracker = new ImpressionTracker(context.getApplicationContext());
        mClickHandler = new NativeClickHandler(context.getApplicationContext());
        JSONArray ads = adResponse.getJsonBody();
        mAdJSONObject = ads.optJSONObject(0);
        initData();
    }

    private void initData() {
        try {
            mClickDestinationUrl = mAdJSONObject.optString("link");
            addImpressionTrackers(mAdJSONObject.optJSONArray("imptrackers"));
            addImpressionTrackers(mAdJSONObject.optJSONArray("clicktrackers"));
            JSONArray jsonArray = mAdJSONObject.optJSONArray("assets");
            for (int i = 0; i < jsonArray.length(); i++) {
                JSONObject paramasJSON = jsonArray.getJSONObject(i);
                for (NativeAssets.AssetType type : NativeAssets.AssetType.values()) {
                    if (paramasJSON.has(type.getKey())) {
                        addInstanceVariable(type, paramasJSON.optJSONObject(type.getKey()));
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void addInstanceVariable(@NonNull final NativeAssets.AssetType assetType,
                                     @Nullable final JSONObject valueJson) {
        switch (assetType) {
            case TITLE:
                setTitle(valueJson.optString("text"));
                break;
            case IMG:
                int imageType = valueJson.optInt("type");
                NativeAssets.ImageAssets imageAssets = NativeAssets.ImageAssets.from(imageType);
                if (imageAssets == NativeAssets.ImageAssets.ICON) {
                    setIconImageUrl(valueJson.optString("url"));
                } else if (imageAssets == NativeAssets.ImageAssets.MAIN_IMAGE) {
                    setMainImageUrl(valueJson.optString("url"));
                }
                break;
            case DATA:
                int dataType = valueJson.optInt("type");
                NativeAssets.DataAssets dataAssets = NativeAssets.DataAssets.from(dataType);
                addDataAssertValue(dataAssets, valueJson.optString("value"));
                break;
            default:
                Logger.d("Unable to add JSON key to internal mapping: " + assetType.getKey());
                break;
        }
    }

    private void addDataAssertValue(NativeAssets.DataAssets dataAssets, String value) {
        switch (dataAssets) {
            case DESC:
                setDesc(value);
                break;
            case DESC2:
                setDesc2(value);
                break;
            case LIKES:
                setLikes(value);
                break;
            case DOWNLOADS:
                setDownloads(value);
                break;
            case RATING:
                setStarRating(Double.valueOf(value));
                break;
            case DISPLAYURL:
                setDisplayUrl(value);
                break;
            case CTATEXT:
                setCallToAction(value);
                break;
        }
    }

    final public void setMainImageUrl(@Nullable String mainImageUrl) {
        this.mMainImageUrl = mainImageUrl;
    }


    final public void setIconImageUrl(@Nullable String iconImageUrl) {
        this.mIconImageUrl = iconImageUrl;
    }

    final public void setClickDestinationUrl(@Nullable String clickDestinationUrl) {
        this.mClickDestinationUrl = clickDestinationUrl;
    }

    final public void setCallToAction(@Nullable String ctaction) {
        this.mCallToAction = ctaction;
    }


    final public void setStarRating(@Nullable Double starRating) {
        this.mStarRating = starRating;
    }

    private void setTitle(@Nullable String mTitle) {
        this.mTitle = mTitle;
    }


    @Nullable
    public String getTitle() {
        return mTitle;
    }


    private void setDesc(String desc) {
        this.mDesc = desc;
    }


    @Override
    String getDesc() {
        return mDesc;
    }

    private void setDesc2(String desc2) {
        this.mDesc2 = desc2;
    }


    @Override
    String getDesc2() {
        return mDesc2;
    }

    private void setSponsored(String sponsored) {
        this.mSponsored = sponsored;
    }


    @Override
    String getSponsored() {
        return mSponsored;
    }

    private void setLikes(String likes) {
        this.mLikes = likes;
    }


    @Override
    String getLikes() {
        return mLikes;
    }

    private void setDownloads(String downloads) {
        this.mDownloads = downloads;
    }


    @Override
    String getDownloads() {
        return mDownloads;
    }

    @Override
    String getDisplayUrl() {
        return mDisplayUrl;
    }


    private void setDisplayUrl(String displayUrl) {
        this.mDisplayUrl = displayUrl;
    }



    @Override
    String getMainImageUrl() {
        return mMainImageUrl;
    }

    @Override
    String getIconImageUrl() {
        return mIconImageUrl;
    }

    @Override
    String getCallToAction() {
        return mCallToAction;
    }

    @Override
    Double getStarRating() {
        return mStarRating != null ? mStarRating : 0.0;
    }

    @Override
    public void registerViewForAction(@NonNull View view) {
        if (isInvalidated()) {
            return;
        }
        mImpressionTracker.addView(view, this);
        mClickHandler.setOnClickListener(view, this);
    }

    @Override
    public void unregisterViewForAction(@NonNull View view) {
        mImpressionTracker.removeView(view);
        mClickHandler.clearOnClickListener(view);

    }

    public void destroy() {
        invalidate();
    }


    @Override
    public void recordImpression(View view) {
        if (isImpressionRecorded() || isInvalidated()) {
            return;
        }
        TrackingRequest.makeTrackingHttpRequest(getImpressionTrackers(), mContext);
        notifyAdImpressed();
    }

    @Override
    public void handleClick(View view) {
        if (isInvalidated()) {
            return;
        }
        mClickHandler.openClickDestinationUrl(mClickDestinationUrl, view);
        TrackingRequest.makeTrackingHttpRequest(getClickTrackers(), mContext);
        notifyAdClicked();
    }

    @Override
    public int getImpressionMinPercentageViewed() {
        return mImpressionMinPercentageViewed;
    }

    @Override
    public Integer getImpressionMinVisiblePx() {
        return mImpressionMinVisiblePx;
    }

    @Override
    public int getImpressionMinTimeViewed() {
        return mImpressionMinTimeViewed;
    }

    @Override
    public boolean isImpressionRecorded() {
        return mImpressionRecorded;
    }

    @Override
    public void setImpressionRecorded() {
        mImpressionRecorded = true;
    }
}
